davila7/claude-code-templates · warning
Access denied
Error message
Access denied
What it means
HTTP 403 from the skill dashboard file route when the requested file path, after path.join + path.normalize, does not stay inside skill.path — i.e. a path traversal (../) attempt or a path that resolves outside the skill directory.
Source
Thrown at cli-tool/src/skill-dashboard.js:416
const skillName = req.params.name;
const filePath = req.params[0]; // Capture the wildcard path
await this.loadSkillsData();
const skill = this.skills.find(s =>
s.name === skillName ||
s.name.toLowerCase().replace(/\s+/g, '-') === skillName.toLowerCase()
);
if (!skill) {
return res.status(404).json({ error: 'Skill not found' });
}
const fullPath = path.join(skill.path, filePath);
// Security check: ensure the file is within the skill directory
const normalizedPath = path.normalize(fullPath);
if (!normalizedPath.startsWith(skill.path)) {
return res.status(403).json({ error: 'Access denied' });
}
if (!(await fs.pathExists(fullPath))) {
return res.status(404).json({ error: 'File not found' });
}
const content = await fs.readFile(fullPath, 'utf8');
const stats = await fs.stat(fullPath);
res.json({
content,
path: filePath,
size: this.formatFileSize(stats.size),
lastModified: stats.mtime,
timestamp: new Date().toISOString()
});
} catch (error) {
console.error('Error loading file:', error);View on GitHub (pinned to a0851ed10c)
Solutions
- Request paths strictly relative to the skill root
- URL-encode the file path and avoid .. segments
- If legitimate file is rejected, verify skill.path is the expected directory
Example fix
// before
fetch(`/api/skills/${name}/file/../../config.json`);
// after
fetch(`/api/skills/${name}/file/${encodeURIComponent(relPath)}`); Defensive patterns
Strategy: validation
Validate before calling
const safeRel = (p) => !p.split('/').includes('..') && !path.isAbsolute(p); Type guard
const isSafeRelPath = (p) => typeof p === 'string' && !p.startsWith('/') && !p.split(/[\\/]/).includes('..'); Prevention
- Never construct file URLs with user-supplied raw paths
- URL-encode relative paths and reject '..' segments client-side
When it happens
Trigger: GET /api/skills/x/file/../../secrets.json, or absolute paths, or encoded traversal sequences that decode to ../ segments.
Common situations: Malicious or buggy frontend requests; manually crafted URLs probing the local server (it binds locally, but the guard still triggers).
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28).
Data as JSON: /api/errors/fbb4671fae675614.
Report an issue: GitHub.