Back to skill

Security audit

api-security-best-practices

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent API security guide with no install-time execution, but it includes refresh-token guidance that could create replayable session tokens if copied into a real app.

Review and revise the refresh-token implementation before installing or relying on this skill. Treat its API security checklist as general guidance, but use hashed or HMACed opaque refresh tokens, token rotation, and replay detection instead of storing raw refresh tokens directly.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:155
Finding
Plaintext Storage of Replayable Refresh Tokens## Vulnerability Details **File Location**: `SKILL.md`, lines 155–163 and 271–278 **Vulnerability Type**: Plaintext storage of sensitive bearer tokens **Risk Level**: Medium The Skill recommends storing complete refresh tokens directly in a database and subsequently locating them through plaintext token equality: ```javascript // Store refresh token in database await db.refreshToken.create({ data: { token: refreshToken, userId: user.id, expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) } }); ``` ```javascript // Check if refresh token exists in database const storedToken = await db.refreshToken.findFirst({ where: { token: refreshToken, userId: decoded.userId, expiresAt: { gt: new Date() } } }); ``` ### Technical Analysis Refresh tokens are bearer credentials: possession is sufficient to exchange them for access tokens. Storing the original token makes every active database record immediately usable if the refresh-token table, a database backup, a replication endpoint, an administrative interface, or an accidentally generated database log is exposed. Unlike password hashes, the stored values require no cracking. The attacker can submit a copied value directly to the documented `/api/auth/refresh` endpoint. The example also does not rotate refresh tokens after successful use or detect reuse of an invalidated token, allowing a stolen token to be replayed repeatedly until it expires or is manually revoked. The use of signed JWT refresh tokens does not mitigate this issue. A valid stolen JWT remains a usable bearer credential even if the attacker does not know its signing secret. ### Attack Path 1. An attacker obtains read access to the refresh-token table or a copy of it through a database disclosure, exposed backup, excessive internal privileges, or another data-access vulnerability. 2. The attacker copies an unexpired plaintext value from the `token` fi ...[truncated 977 chars]
Remediation
## Remediation Suggestions 1. Replace JWT refresh tokens with opaque, cryptographically random tokens generated using a secure random-number generator. 2. Return the original opaque token only to the client and store a keyed hash, such as HMAC-SHA-256 with a server-held key, in the database. 3. Hash the token presented to the refresh endpoint and compare that derived value with the stored digest. Use constant-time comparison where application-level comparisons are performed. 4. Rotate the refresh token after every successful refresh. Atomically invalidate the previous token before issuing and storing the replacement. 5. Organize tokens into session or token families. If an invalidated token is reused, revoke the entire family and require the user to authenticate again. 6. Preserve expiration, revocation, user, device, and creation metadata, but never log or persist the raw bearer token outside the client response. 7. Protect the hashing or HMAC key through a secret manager and rotate it under a documented key-rotation procedure. 8. Restrict database and backup access according to least privilege, encrypt backups, and monitor unusual reads of the token table. 9. For browser clients, deliver refresh tokens through `Secure`, `HttpOnly`, and appropriately configured `SameSite` cookies, with CSRF protections where required.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (4)

Credential Access

High
Category
Privilege Escalation
Content
if (!token) {
    return res.status(401).json({ 
      error: 'Access token required' 
    });
  }
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
});
    }
    
    // Generate new access token
    const user = await db.user.findUnique({
      where: { id: decoded.userId }
    });
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### Security Best Practices

- ✅ Use strong JWT secrets (256-bit minimum)
- ✅ Set short expiration times (1 hour for access tokens)
- ✅ Implement refresh tokens for long-lived sessions
- ✅ Store refresh tokens in database (can be revoked)
- ✅ Use HTTPS only
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### Security Best Practices

- ✅ Use strong JWT secrets (256-bit minimum)
- ✅ Set short expiration times (1 hour for access tokens)
- ✅ Implement refresh tokens for long-lived sessions
- ✅ Store refresh tokens in database (can be revoked)
- ✅ Use HTTPS only
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.