
Putting models to the secure coding test: Security rules
Second post in a Datadog Security Labs series testing whether Project CodeGuard (v1.4.0) security rules improve code written by coding agents. Sonnet 5 (Claude Code), Composer 2.5 (Cursor) and GPT 5.5 (Codex) each built the same document portal, and the output was audited with Datadog Code Security and a Sonnet 5 code review. Only GPT 5.5 closed the cross-user IDOR; Sonnet 5 and Composer 2.5 stayed largely unchanged, including hardcoded JWT secret fallbacks and incomplete revocation.
What it is
A single-run experiment by Datadog Security Labs, the second in a series, testing whether Project CodeGuard v1.4.0 security rules change the security of code written by coding agents. Three harness and model pairs each built the same "document portal" from one prompt: Claude Code with Sonnet 5, Cursor with Composer 2.5, and Codex with GPT 5.5. The prompt asked for a JavaScript and PostgreSQL app with JWT plus session cookies, roles, password reset, search, file upload, comments and profile editing. It did not say who may see uploaded documents.
How it works
CodeGuard was installed once per harness and then ran in the background. For Claude Code it came from the plugin marketplace, scoped to the project folder. For Cursor and Codex it came from a zip and the installation guide's commands. Supply Chain Firewall blocked outdated or vulnerable dependencies. Output was checked with Datadog Code Security (SCA, SAST, IaC) and a Sonnet 5 code_review pass. The no-rules baselines were reused from part one.
Results with rules
| Model | Cross-user document IDOR | Other findings |
|---|---|---|
| Sonnet 5 | Still present | Revocation checked only in CSRF middleware, so a deactivated or logged-out user keeps read access for up to the 15-minute access token life. Session fingerprints captured but never compared. |
| Composer 2.5 | Still present | Critical: JWTs verified by signature and expiry only, kept in localStorage, valid up to 24 hours after logout or password reset. JWT_SECRET and SESSION_SECRET fall back to hardcoded values. Uploads trusted client MIME type and extension. |
| GPT 5.5 | Closed | Reset requests do not invalidate earlier tokens. Argon2id hashing runs before token validation. ip_hash is computed but never compared. |
Composer 2.5's requireEnv helper applies the fallback before the production check, so the check never fires. Rules added rate limiting on its auth routes, which the baseline lacked.
GPT 5.5 also gained double-submit CSRF with Origin and Sec-Fetch-Site checks and magic-byte upload validation, fixing the baseline's CSRF and MIME problems. It pinned exact dependency versions, while the other two kept ^ ranges.
Sonnet 5 with rules showed a regression: the baseline already had revocation on logout, and the rules build moved the check to CSRF-protected routes only.
What to do
The author's recommendation is to put persistent guidance in the security rules or the global agent file, and to state access constraints in the prompt, for example "filter every document query by owner". The suggested global rule:
# ~/.config/agents/AGENTS.md
Always implement a dependency cooldown of 7 days unless otherwise specified. If the package manager does not support this, do not configure the dependency to automatically upgrade to the next version.Caveats
Each model ran once, and the author notes that nondeterminism means other runs could differ. Findings come from automated scanning and one model's review, with full detail in the linked repository. The author concludes that the rules help but are not specific enough to guarantee a fix, and that the missing access requirement in the prompt explains the IDOR.
Technologies named here
- Project CodeGuard
- Claude Code
- Cursor
- Codex
- Supply Chain Firewall
- Datadog Code Security
- GPT-5.5
- Node.js
- PostgreSQL
- AGENTS.md
- AGENTS.md / claude.md
- Claude code_review skill (Sonnet 5)
- Composer 2.5 with Project CodeGuard (Cursor): IDOR, JWTs valid up to 24 hours after logout or password reset, hardcoded JWT_SECRET and SESSION_SECRET fallbacks, client-supplied MIME type and extension upload validation
- GPT 5.5 with Project CodeGuard (Codex): ip_hash never compared during auth checks, earlier password-reset tokens not invalidated, Argon2id hashing before token validity check
- Sonnet 5 with Project CodeGuard v1.4.0 (Claude Code): document-ownership IDOR, revocation checked only in CSRF middleware, session fingerprints never compared
Techniques named here
- Cross-Site Request Forgery
- Parameterized queries
- IDOR
- CSRF
- Account enumeration
- Argon2id password hashing
- Dependency version pinning and cooldowns
- Double-submit CSRF protection
- Hardcoded secret fallback
- Magic-byte file upload validation
- Refresh token rotation
- Server-side session revocation
Related in AI Security
