Odin is a Burp Suite extension that passively inspects HTTP traffic and reports missing or misconfigured security headers.
It works with both Community and Professional editions via the Montoya API. Findings appear automatically as you browse — no manual triggering required.
- Proxy > HTTP history — color-coded highlight and note on each flagged request
- Extensions > Odin > Output — full findings log
| Category | Headers / Attributes |
|---|---|
| CORS | Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers |
| Cookie attributes | Secure, HttpOnly, SameSite, Expires / Max-Age, Path, Domain |
| Security headers | X-Content-Type-Options, Strict-Transport-Security, X-Frame-Options / CSP frame-ancestors, Content-Security-Policy, Referrer-Policy, Permissions-Policy |
Note: Severity levels are based on the author's personal judgment — none of the referenced sources assign explicit severity ratings. If you disagree, feel free to open an issue or fork and tweak the values to suit your needs.
| Severity | Category | Trigger condition | Example (response header) | Reference |
|---|---|---|---|---|
| HIGH | CORS | ACAO reflects the request Origin |
Access-Control-Allow-Origin: https://evil.com (mirrors Origin: https://evil.com) |
OWASP |
| HIGH | CORS | ACAO reflects Origin and ACAC: true |
Access-Control-Allow-Origin: https://evil.comAccess-Control-Allow-Credentials: true |
OWASP |
| HIGH | CORS | ACAO: * and ACAC: true |
Access-Control-Allow-Origin: *Access-Control-Allow-Credentials: true |
OWASP |
| MEDIUM | CORS | ACAO: * |
Access-Control-Allow-Origin: * |
OWASP |
| MEDIUM | Cookie | HTTPS response, Set-Cookie has no Secure |
Set-Cookie: session=abc; HttpOnly |
MDN |
| MEDIUM | Cookie | SameSite=None without Secure |
Set-Cookie: session=abc; SameSite=None |
MDN |
| MEDIUM | Security | HTTPS response, Strict-Transport-Security absent |
(header absent) | MDN |
| LOW | CORS | ACAM contains PUT, DELETE, or PATCH |
Access-Control-Allow-Methods: GET, POST, PUT, DELETE |
OWASP |
| LOW | Cookie | Set-Cookie has no HttpOnly |
Set-Cookie: session=abc; Secure |
MDN |
| LOW | Cookie | Set-Cookie has no SameSite |
Set-Cookie: session=abc; Secure; HttpOnly |
MDN |
| LOW | Cookie | SameSite=None (even with Secure) |
Set-Cookie: session=abc; Secure; SameSite=None |
MDN |
| LOW | Security | X-Frame-Options absent and CSP has no frame-ancestors |
(both absent, or CSP present but without frame-ancestors) |
MDN |
| LOW | Security | Content-Security-Policy absent |
(header absent) | OWASP |
| LOW | Security | X-Content-Type-Options absent |
(header absent) | MDN |
| LOW | Security | X-Content-Type-Options value is not nosniff |
X-Content-Type-Options: sniff |
MDN |
| LOW | Security | max-age < 31536000 (1 year) |
Strict-Transport-Security: max-age=3600 |
MDN |
| LOW | Security | Referrer-Policy is unsafe-url or no-referrer-when-downgrade |
Referrer-Policy: unsafe-urlReferrer-Policy: no-referrer-when-downgrade |
MDN |
| INFORMATION | Cookie | Set-Cookie has neither Expires nor Max-Age |
Set-Cookie: session=abc; Secure; HttpOnly |
MDN |
| INFORMATION | Cookie | Set-Cookie has Path=/ |
Set-Cookie: session=abc; Path=/ |
MDN |
| INFORMATION | Cookie | Set-Cookie has a Domain= attribute |
Set-Cookie: session=abc; Domain=.example.com |
MDN |
| INFORMATION | Security | Strict-Transport-Security has no includeSubDomains |
Strict-Transport-Security: max-age=31536000 |
MDN |
| INFORMATION | Security | Referrer-Policy absent |
(header absent) | MDN |
| INFORMATION | Security | Permissions-Policy absent |
(header absent) | MDN |
| LOW | CORS | ACAH: * |
Access-Control-Allow-Headers: * |
OWASP |
- Nix Flake
- Java: 21
- Gradle: 8.7
- montoya-api: 2026.2
- Shadow plugin: 8.3.5 (
com.gradleup.shadow) - jacoco
- tested on Burp Suite Community Edition 2026.2.3 Linux(x64)
-
Build the JAR (or download a release):
./gradlew shadowJar # Output: build/libs/odin-0.0.1.jar[!NOTE] You can download
.jarfrom latest Releases -
Open Burp Suite and go to Extensions > Add.
- Extension type: Java
- Select file:
build/libs/odin-0.0.1.jar
-
Browse the target application through Burp Proxy as usual.
-
Check findings in Proxy > HTTP history (color-coded highlights and notes) or Extensions > Odin > Output (full log).
Note
Odin only performs passive analysis on already-captured traffic. It never sends additional requests to the target.
# Enter the dev shell (provides Java 21 + Gradle automatically via direnv)
direnv allow
# or manually:
nix develop./gradlew shadowJar
# Output: build/libs/odin-0.0.1.jar./gradlew fmt-
Update the version in
build.gradle.kts. -
Update any version strings in
README.md(JAR filename examples). -
Run tests and build the JAR:
./gradlew test shadowJar -
Commit the version bump:
git add build.gradle.kts README.md git commit -m "Release vX.Y.Z" -
Create a tag and push:
git tag vX.Y.Z git push git push --tags
This extension is designed to meet the acceptance criteria for the BApp Store.
Yes. There is no existing BApp that performs comprehensive passive linting of security response headers (CORS, Cookie attributes, HSTS, CSP, Referrer-Policy, Permissions-Policy) as scanner issues in a single extension.
Yes.
The extension name is set to Odin - Security Header Linter and clearly describes its function.
Yes.
- All HTTP header values are treated as untrusted input.
- Header values are never directly reflected in output; findings reference only hardcoded
IssueDefinitionnames and static descriptions. - No
eval, reflection, or shell execution of header data.
Yes.
montoya-api is declared compileOnly (Burp provides it at runtime). All other dependencies are bundled via the Shadow plugin into a single fat JAR. See build.gradle.kts.
Yes.
handleResponseReceived() is invoked by Burp on its own proxy thread. The extension performs no Swing EDT operations and no blocking I/O.
Yes.
api.extension().registerUnloadingHandler() is called in OdinExtension.initialize().
Out of scope. This extension makes no outbound HTTP requests. It only inspects already-captured traffic.
Yes. The extension operates entirely offline — all checks are pure in-memory analysis of HTTP messages.
Yes.
- No long-term references to
HttpRequestResponseobjects are held. - Each
handleResponseReceived()invocation is stateless.
Out of scope. This extension adds no custom GUI tabs or dialogs. All output is through Burp's native scanner issue panel.
Yes.
net.portswigger.burp.extensions:montoya-api is referenced via Gradle as required.
Out of scope. This extension does not use AI features.
