Attack SAML single sign-on by decoding and tampering with signed XML assertions — XML signature wrapping (XSW1-XSW8), signature stripping, assertion and attribute tampering, NameID comment…
Install the "attacking-saml" agent skill from https://github.com/trilwu/secskills/tree/main/secskills-offense/skills/attacking-saml into .claude/skills/attacking-saml/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "attacking-saml", then confirm the skill loads.
Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Type this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
skills CLI
$ npx skills add trilwu/secskills --skill attacking-saml -a codex
Project install goes to .agents/skills/; add -g for ~/.codex/skills/.
Install the "attacking-saml" agent skill from https://github.com/trilwu/secskills/tree/main/secskills-offense/skills/attacking-saml into .agents/skills/attacking-saml/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "attacking-saml", then confirm the skill loads.
Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add trilwu/secskills --skill attacking-saml -a cursor
Project install goes to .agents/skills/; add -g for ~/.cursor/skills/.
Install the "attacking-saml" agent skill from https://github.com/trilwu/secskills/tree/main/secskills-offense/skills/attacking-saml into .cursor/skills/attacking-saml/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "attacking-saml", then confirm the skill loads.
Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
skills CLI
$ npx skills add trilwu/secskills --skill attacking-saml -a gemini-cli
Project install goes to .agents/skills/; add -g for ~/.gemini/skills/.
Install the "attacking-saml" agent skill from https://github.com/trilwu/secskills/tree/main/secskills-offense/skills/attacking-saml into .gemini/skills/attacking-saml/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "attacking-saml", then confirm the skill loads.
Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Installs for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
skills CLI
$ npx skills add trilwu/secskills --skill attacking-saml -a github-copilot
Project install goes to .agents/skills/; add -g for ~/.copilot/skills/.
Install the "attacking-saml" agent skill from https://github.com/trilwu/secskills/tree/main/secskills-offense/skills/attacking-saml into .github/skills/attacking-saml/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "attacking-saml", then confirm the skill loads.
GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
skills CLI
$ npx skills add trilwu/secskills --skill attacking-saml -a opencode
OpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
Install the "attacking-saml" agent skill from https://github.com/trilwu/secskills/tree/main/secskills-offense/skills/attacking-saml into .opencode/skills/attacking-saml/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "attacking-saml", then confirm the skill loads.
OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
Facts
Skill name
attacking-saml
GitHub stars
156
Token cost
~3.5k tokens
SKILL.md length
1,629 words
Files
1
Skills in repo
50
Repo updated
First seen
Licence
MIT
At a glance
Attack SAML single sign-on by decoding and tampering with signed XML assertions — XML signature wrapping (XSW1-XSW8), signature stripping, assertion and attribute tampering, NameID comment…
A request carries a SAMLRequest
SKILL.md covers When to Use, When NOT to Use, Decode and Inspect and XML Signature Wrapping (XSW), plus 10 more sections
Calls python3 and openssl
SAMLResponse parameter
What it does
Attacking Saml is an agent skill from trilwu/secskills. Attack SAML single sign-on by decoding and tampering with signed XML assertions — XML signature wrapping (XSW1-XSW8), signature stripping, assertion and attribute tampering, NameID comment injection, XXE through the SAML parser, certificate faking, recipient confusion and IdP-initiated replay, and Golden SAML forgery. Use when a request carries a SAMLRequest or SAMLResponse parameter, when base64+deflate decodes to XML with <saml:Assertion, when the target exposes a /saml/acs or /sso endpoint, when an…
Its SKILL.md is about 3.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Authentication. It works with Microsoft Azure and Okta. The repository describes itself as: Transform Claude Code into your personal security engineer. The licence is MIT.
When your agent uses it
A request carries a SAMLRequest
SAMLResponse parameter
Base64+deflate decodes to XML with <saml:Assertion
The target exposes a /saml/acs
Example prompts
“/attacking-saml”
Requirements
Python 3
What it can do on your machine
Read from SKILL.md and the folder at commit ca53957. It shows what the files ask for, not the result of running them.
Tool permissions
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Runs code
Shell commands in SKILL.md call:
python3
openssl
From the folder's file list and the shell code blocks in SKILL.md.
Network
Links to these hosts (documentation or services it may open):
attack.mitre.org
From URLs in SKILL.md, links to its own repository left out.
Credentials
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Context cost
Attacking Saml loads about 3.5k tokens when it runs. Until then it costs about 162 tokens; SKILL.md has 1,629 words of instructions outside code blocks.
Always· name and description, kept in context so the agent knows when to use it
~162
When it runs· the whole SKILL.md, loaded when a task matches
~3.5k
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
Safety
Auto-check passed
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
Download SKILL.mdSave it as .claude/skills/attacking-saml/SKILL.md (or your agent's skills folder).
name
attacking-saml
description
Attack SAML single sign-on by decoding and tampering with signed XML assertions — XML signature wrapping (XSW1-XSW8), signature stripping, assertion and attribute tampering, NameID comment injection, XXE through the SAML parser, certificate faking, recipient confusion and IdP-initiated replay, and Golden SAML forgery. Use when a request carries a `SAMLRequest` or `SAMLResponse` parameter, when base64+deflate decodes to XML with `<saml:Assertion>`, when the target exposes a `/saml/acs` or `/sso` endpoint, when an IdP-initiated login lands an assertion at the SP, or when federation runs through Okta, ADFS, Ping, or Azure/Entra.
verified
2026-07-26
Attacking SAML
SAML security is XML signature validation, and XML signatures are notoriously
hard to validate correctly. The assertion is signed — but which element is
signed, what the XML parser reads, and what the application ultimately trusts
can be three entirely different things. That gap is XML Signature Wrapping,
and it is the reason SAML breaks far more often than its cryptography suggests.
Only against systems you are authorized to test.
When to Use
A request or redirect carries a SAMLRequest or SAMLResponse parameter
Base64 (plus DEFLATE for the redirect binding) decodes to XML containing
<saml:Assertion>, <samlp:Response>, or <saml:Subject>
The target exposes a /saml/acs, /sso, /saml2/acs, or /Shibboleth.sso
Assertion Consumer Service endpoint
An IdP-initiated login POSTs an assertion straight to the SP with no prior
AuthnRequest
Federation runs through Okta, ADFS, PingFederate, Azure/Entra, Shibboleth,
SimpleSAMLphp, or Keycloak
You control a low-privilege federated account and want to reach another
identity or role
When NOT to Use
The SSO flow is OAuth 2.0 or OpenID Connect (code, id_token,
access_token, /authorize, /.well-known/openid-configuration) — use
attacking-oauth-oidc
The token is a JWT (eyJ... with dot separators) rather than signed
XML — use attacking-jwt
General web testing with no SAML artifact in scope — use
testing-web-applications
Golden SAML against a compromised AD FS server or cloud tenant where you
already hold the token-signing key — that is a tenant-takeover play in
attacking-entra-id
Evaluating the signature primitives themselves (SHA-1 vs SHA-256, RSA
key size, canonicalization algorithm choice) — use reviewing-cryptography
Decode and Inspect
Everything starts with reading the message. The wire format depends on the
binding.
bash
# HTTP-Redirect binding: base64 then raw DEFLATE (no zlib header)
echo 'fVLLbtsw...' | base64 -d | python3 -c \
"import sys,zlib; sys.stdout.write(zlib.decompress(sys.stdin.buffer.read(),-15).decode())"
# HTTP-POST binding: plain base64, no deflate
echo 'PHNhbWxwOl...' | base64 -d | xmllint --format -
The redirect binding uses raw DEFLATE — window bits -15, no header. The POST
binding does not deflate at all. Guess wrong and you get garbage; try both.
SAML Raider (Burp extension) is the working environment: it intercepts the
ACS POST, pretty-prints the XML, imports the IdP certificate, and drives the
signature-wrapping attacks below with a single click. Install it before doing
anything by hand.
samltool.com (SAMLtool by OneLogin) decodes and re-encodes messages and is
useful for understanding structure — but treat it as offline reference only.
Never paste a live production assertion into a third-party website; decode with
the commands above instead.
Read these fields first, because they define every attack that follows:
<ds:Signature> — where it sits and what its <ds:Reference URI="#...">
points to. This is the whole game.
<saml:Subject><saml:NameID> — the identity being asserted
The core SAML attack. The signature is cryptographically valid, but you move
the signed element somewhere the signature checker still accepts it while the
application logic reads a different, unsigned assertion that you control. The
verifier and the consumer disagree about which element is authoritative.
The eight canonical variants (Somorovsky et al.) differ in where the original
signed assertion is relocated and where the forged one is injected:
XSW1 / XSW2 — wrap the whole <Response>; the signature references the
original response while a forged response is processed. XSW2 uses a
non-enveloping signature position.
XSW3 / XSW4 — assertion-level. XSW3 makes the forged assertion a
sibling of the signed one; XSW4 nests the signed assertion inside the
forged one. Same or overlapping IDs.
XSW5 / XSW6 — the copied assertion envelopes the signature; play games
with the ID attribute so the reference still resolves.
XSW7 / XSW8 — hide in a loose-schema wrapper. XSW7 puts the forged
assertion in an <Extensions> element; XSW8 buries the original signed one
in an <Object> so it validates but is never consumed.
# Attack in SAML Raider:
# 1. Intercept the ACS POST, select the signed assertion
# 2. Edit NameID / attributes in the assertion the app will read
# 3. Click XSW1..XSW8 in turn — each rebuilds the document layout
# 4. Forward; watch for a successful login as the forged identity
Iterate through all eight. Which one works depends entirely on the SP's XML
library and how it selects the assertion to trust — there is no way to predict
it, so try every variant before concluding the SP is safe. A successful login
as a NameID you never legitimately held is the finding.
Unsigned Assertions and Signature Stripping
Before the wrapping games, test the simplest failure: does the SP verify a
signature at all?
Strip the signature. Remove <ds:Signature> entirely and forward. Some
SPs only verify a signature if one is present.
Empty the signature. Blank the SignatureValue or DigestValue.
Sign the wrong thing. Sign the response but not the assertion, or vice
versa, when the SP only checks one.
Downgrade the algorithm. Try SignatureMethod of SHA-1 or even
md5/no-op where the SP does not pin the expected algorithm.
bash
# xmlsec1 can tell you what a document's signature actually covers
xmlsec1 --verify --pubkey-cert-pem idp.crt --id-attr:ID Assertion response.xml
If the SP accepts a stripped or unsigned assertion, you can forge identity with
no cryptography at all — the highest-severity SAML outcome.
Assertion Tampering
Once you can get an assertion accepted (stripped, unsigned, or via a working
XSW variant), change what it claims:
NameID — swap to a target user (admin@corp, another tenant's user)
Attributes — flip Role/Group/memberOf to admin, add
entitlement attributes the IdP never issued, change email to trigger
account linking on the SP
AudienceRestriction — if the SP does not check <Audience>, an assertion
minted for another SP in the same federation is replayable here
NotOnOrAfter / NotBefore — a wide or unchecked validity window lets you
replay a captured assertion long after it should have expired
InResponseTo — for the SP-initiated flow, whether the SP binds the
response to its own AuthnRequest ID; if not, injected/replayed responses
are accepted
Test each independently. An SP that validates the signature but ignores
AudienceRestriction or the replay window is still fully exploitable.
Comment Injection in NameID
A canonicalization bug in several SAML libraries (the 2018 Duo/python-saml/
OneLogin class of CVEs). XML text-node handling and signature
canonicalization disagree about how an XML comment splits a text node.
xml
<saml:NameID>admin<!---->@evil.com</saml:NameID>
The signature is computed over the canonicalized value (which may drop the
comment or concatenate the nodes), while the application's text extraction
reads only the node before the comment — yielding admin. So a validly
signed assertion for admin@evil.com (an account you legitimately own)
authenticates you as admin. Try comments inside any identity-bearing field:
NameID, and email/username attributes used for account mapping.
Show full SKILL.md (659 more words)Show less
XXE via the SAML Parser
The SP feeds attacker-supplied XML into a parser. If external entities are not
disabled, the ACS endpoint is an XXE sink.
Use an out-of-band DTD (http://attacker/evil.dtd) for blind file read and
SSRF into the SP's internal network. The full technique — parameter entities,
OOB exfiltration, error-based leakage — is in exploiting-xxe; the SAML angle
is simply that the assertion is the injection point and the ACS is
unauthenticated.
Certificate Faking and Self-Signed Re-Signing
If the SP does not pin the IdP's certificate — instead trusting whatever cert
is embedded in <ds:KeyInfo>, or accepting any cert from a broad CA bundle —
you can strip the real signature, re-sign with your own key, and ship your cert
in the message.
SAML Raider automates this: "Send Certificate" imports/generates a cert, then
resigns the edited message in place. If the forged self-signed assertion is
accepted, the SP is trusting the message's own embedded key instead of a
pinned IdP cert — complete authentication bypass.
Recipient / Destination Confusion and IdP-Initiated Replay
Recipient / Destination not checked. If the SP ignores the Recipient
in SubjectConfirmationData or the Destination on the response, an
assertion captured at one SP replays at another that shares the IdP.
IdP-initiated replay. IdP-initiated SSO has no AuthnRequest to bind to,
so there is no InResponseTo and often no anti-replay state. Capture a valid
IdP-initiated POST and re-send it — within the validity window it may log you
straight back in. A leaked assertion in logs, referrers, or history becomes a
usable credential.
Token reuse across tenants. In multi-tenant SaaS, check whether an
assertion issued for tenant A is accepted at tenant B's ACS.
Golden SAML
The endgame, not the entry point. If you already hold the IdP's private
token-signing key (stolen from an AD FS server's certificate store, an
Azure/Entra federation trust, or an exported IdP keystore), you forge
arbitrary, perfectly-signed assertions for any user, any role, indefinitely —
no credentials, no MFA, no IdP interaction, and it survives password resets.
bash
# With the stolen signing key, mint an assertion for any identity
xmlsec1 --sign --privkey-pem tokensigning.key,tokensigning.crt \
--id-attr:ID Assertion golden.xml > any-user.xml
Obtaining the key is a host/tenant-compromise task, not a SAML-message task —
that path (extracting the AD FS token-signing cert, DKM key, or cloud
federation secret) lives in attacking-entra-id. Come back here only to shape
the forged assertion.
Rationalizations to Reject
"The assertion is signed, so it can't be tampered with." Signature
wrapping keeps the signature valid while the app reads a different element.
Signed does not mean the signed thing is what gets trusted.
"XSW1 didn't work, so the SP is safe." There are eight variants for a
reason. Run all of XSW1–XSW8 before concluding anything.
"It verifies the signature — I checked." Verifying a signature is not
verifying the assertion you consume. And it may only verify when one is
present; strip it and test.
"The audience/recipient is just metadata." If the SP doesn't enforce
AudienceRestriction, Recipient, and Destination, assertions replay
across SPs and tenants.
"The comment thing is cosmetic."admin<!---->@evil.com authenticates as
admin. Canonicalization mismatches are full account takeover.
"It's XML from a trusted IdP, so XXE isn't a concern." The ACS parses the
bytes before it trusts them, and the bytes come from your browser. Untrusted.
"Golden SAML needs the private key, so it's out of scope." Forging the
assertion is in scope here; note the exposure and route key extraction to
attacking-entra-id — don't dismiss the impact.
<!-- attack:start -->
ATT&CK Coverage
Generated from secskills-core/ttp-index.json — edit that file, then run
python3 scripts/sync_attack.py --write. Re-verify IDs against the
current ATT&CK release before citing them in a report.
Credential Access (TA0006)
T1606.002 SAML Tokens — see also attacking-entra-id
Detection content for any of these: engineering-detections. Proactive search: hunting-threats. Post-compromise: responding-to-incidents.
<!-- attack:end -->
References
attacking-oauth-oidc — when the SSO flow is OAuth 2.0 / OpenID Connect
attacking-jwt — when the token is a signed JWT rather than XML
exploiting-xxe — full XXE technique when the ACS parser is the sink
attacking-entra-id — Golden SAML via a compromised AD FS server or tenant
testing-web-applications — the surrounding web methodology
reporting-security-findings — severity for signature-bypass and replay
Attacking Saml next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
Implement Okta as a centralized cloud identity provider: configure SSO with AWS, Azure, and GCP, deploy phishing-resistant MFA with Okta FastPass, automate user provisioning/deprovisioning, and…
A skill your agent uses when implementing authorization and access control for FrontMCP tools, resources, prompts, or skills, deciding who may invoke what.
Activate when code touches token management, credential resolution, git auth flows, GITHUBAPMPAT, ADOAPMPAT, AuthResolver, HostInfo, AuthContext, or any remote host authentication -- even if 'auth'…
Assess and harden LLM applications and agentic systems against prompt injection, tool misuse, excessive agency, memory poisoning, RAG data leakage, and model supply-chain risk, mapped to the OWASP…
Reverse engineer Go binaries by recovering function names and types from pclntab and moduledata using GoReSym, redress, and IDA/Ghidra Go plugins, and by reading Go's non-standard calling…
Analyze iOS applications at the binary level — decrypting FairPlay-protected IPAs with frida-ios-dump or bagbak, inspecting Mach-O load commands, recovering Objective-C headers with class-dump, and…
Attack SAML single sign-on by decoding and tampering with signed XML assertions — XML signature wrapping (XSW1-XSW8), signature stripping, assertion and attribute tampering, NameID comment…. Attacking Saml is an agent skill from trilwu/secskills. Attack SAML single sign-on by decoding and tampering with signed XML assertions — XML signature wrapping (XSW1-XSW8), signature stripping, assertion and attribute tampering, NameID comment injection, XXE through the SAML parser, certificate faking, recipient confusion and IdP-initiated replay, and Golden SAML forgery.
When should I use Attacking Saml?
Attacking Saml fits situations like: A request carries a SAMLRequest; SAMLResponse parameter; base64+deflate decodes to XML with <saml:Assertion; the target exposes a /saml/acs.
How do I install Attacking Saml in Claude Code?
Run `npx skills add trilwu/secskills --skill attacking-saml -a claude-code`. Or copy the skill folder (secskills-offense/skills/attacking-saml in trilwu/secskills) into .claude/skills/attacking-saml in your project. Claude Code loads it when a task matches its description.
How do I install Attacking Saml in Codex?
Run `npx skills add trilwu/secskills --skill attacking-saml -a codex`. Or copy the skill folder (secskills-offense/skills/attacking-saml in trilwu/secskills) into .agents/skills/attacking-saml in your project. Codex loads it when a task matches its description.
Can I use Attacking Saml in Cursor, Gemini CLI or GitHub Copilot?
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add trilwu/secskills --skill attacking-saml -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/attacking-saml, .gemini/skills/attacking-saml, .github/skills/attacking-saml and .opencode/skills/attacking-saml in your project.
What does Attacking Saml need to run?
Going by SKILL.md and its folder, Attacking Saml needs the command-line tools its instructions call (python3 and openssl). Our summary lists: Python 3.
Does Attacking Saml access the network?
SKILL.md names 1 domain. As links in the text: attack.mitre.org. This is read from the text; nothing was executed.
Is Attacking Saml safe to install?
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
What licence does Attacking Saml use?
Attacking Saml is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
How many tokens does Attacking Saml use?
About 3.5k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
What are the alternatives to Attacking Saml?
Skills that share tags, products or a category with Attacking Saml: Managing Cloud Identity With Okta (mukul975/Anthropic-Cybersecurity-Skills, 34k stars), Iam Audit (briiirussell/cybersecurity-skills, 413 stars), API Security Design (vinayaklatthe/microsoft-security-skills, 175 stars) and Frontmcp Authorities (agentfront/frontmcp, 146 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Who maintains Attacking Saml?
trilwu (a GitHub user) maintains it in trilwu/secskills, which has 156 GitHub stars. The repository holds 50 skills in this directory. The repository was last updated on September 4, 2026.
Source: trilwu/secskills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.