audit-security — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited audit-security (Agent Skill) and scored it 45/100 (orange). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.
*.sig, SIGNATURES) outside the documentation.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Systematic security review for any web application. Research-driven, using current OWASP guidelines.
Before auditing, discover the tech stack and attack surface:
package.json / requirements.txt / go.mod to identify:Fetch current OWASP and security best practices for the detected stack:
CallMcpTool(server: "user-firecrawl", toolName: "firecrawl_search", arguments: {
"query": "<framework> security best practices OWASP <current year>",
"limit": 5,
"sources": [{ "type": "web" }]
})Scrape the OWASP Top 10 for the relevant platform:
CallMcpTool(server: "user-firecrawl", toolName: "firecrawl_scrape", arguments: {
"url": "https://owasp.org/Top10/",
"formats": ["markdown"],
"onlyMainContent": true
})Also check for known CVEs in dependencies:
CallMcpTool(server: "user-firecrawl", toolName: "firecrawl_search", arguments: {
"query": "<package-name> CVE vulnerability <current year>",
"limit": 5,
"sources": [{ "type": "web" }]
})If Sentry is configured, check for security-related production errors:
CallMcpTool(server: "plugin-sentry-sentry", toolName: "search_issues", arguments: {
"organizationSlug": "<ORG_SLUG>",
"naturalLanguageQuery": "401 unauthorized OR 403 forbidden OR CORS OR CSP violation in last 30 days",
"projectSlugOrId": "<PROJECT_SLUG>",
"regionUrl": "<REGION_URL>",
"limit": 20
})Patterns that indicate security issues:
eval(), Function(), innerHTML with user inputdangerouslySetInnerHTML without DOMPurifytype="password" and autocomplete="new-password"Strict-Transport-Security (HSTS) with long max-ageContent-Security-Policy (CSP) configured (not just default-src *)X-Content-Type-Options: nosniffX-Frame-Options: DENY or SAMEORIGINReferrer-Policy: strict-origin-when-cross-origin or stricterPermissions-Policy restricting unnecessary browser featuresAccess-Control-Allow-Origin is NOT * for authenticated endpointsHttpOnly, Secure, SameSite=Strict (or Lax)npm audit # Node.js
pip-audit # Python
cargo audit # Rust
govulncheck ./... # Go
bundle audit # Rubypackage-lock.json, yarn.lock, pnpm-lock.yaml)// VULNERABLE
const query = `SELECT * FROM users WHERE id = '${userId}'`;
// SAFE — parameterized
const query = 'SELECT * FROM users WHERE id = $1';
db.query(query, [userId]);
// SAFE — ORM
User.findById(userId);// VULNERABLE
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// SAFE — React escapes by default
<div>{userInput}</div>
// SAFE — sanitize when HTML is genuinely needed
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />// VULNERABLE — no ownership check
app.get('/documents/:id', (req, res) => {
const doc = db.documents.findById(req.params.id);
res.json(doc);
});
// SAFE — verify ownership
app.get('/documents/:id', (req, res) => {
const doc = db.documents.findOne({
where: { id: req.params.id, userId: req.user.id }
});
if (!doc) return res.status(404).json({ error: 'Not found' });
res.json(doc);
});// VULNERABLE — leaking sensitive fields
res.json(user); // includes passwordHash, tokens, internal IDs
// SAFE — explicit field selection
const { id, name, email, avatar } = user;
res.json({ id, name, email, avatar });Search the codebase for potential leaked secrets:
Grep for: api_key, apiKey, secret, password, token, credentials, private_key
Grep for: sk-, pk-, ghp_, gho_, xox[bpsa]-, AKIA
Grep for: -----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY-----.env, .env.local, .env.production
*.pem, *.key, *.p12
credentials.json, service-account.json
.sentryclirc (if it contains auth tokens)import { z } from 'zod';
const envSchema = z.object({
DATABASE_URL: z.string().url(),
API_KEY: z.string().min(1),
JWT_SECRET: z.string().min(32),
SENTRY_DSN: z.string().url().optional(),
});
const env = envSchema.parse(process.env);## Security Audit: [Project Name]
### Tech Stack
- Framework: [name + version]
- Auth: [library + pattern]
- Database: [ORM + provider]
- Security packages: [list]
### Critical Issues (must fix)
| # | Category | Finding | File | Recommendation |
|---|----------|---------|------|----------------|
| 1 | Auth | JWT secret hardcoded | config.ts:12 | Move to env var |
### High Risk (should fix soon)
| # | Category | Finding | File | Recommendation |
|---|----------|---------|------|----------------|
### Medium Risk (improve when possible)
| # | Category | Finding | File | Recommendation |
|---|----------|---------|------|----------------|
### Passed Checks
- [list of security areas that are properly implemented]
### Dependencies
- Critical CVEs: [count] — [details]
- High CVEs: [count]
- Outdated packages: [count]
### Research Sources
- [URL] — [what it confirmed or revealed]~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.