Interlace ESLint
ESLint Interlace
Secure CodingRules

no-directive-injection

Detects directive injection vulnerabilities in template systems. This rule is part of [`eslint-plugin-secure-coding`](https://www.npmjs.com/package/eslint-plugi

Keywords: directive injection, CWE-94, template injection, Angular, Vue, React, SSTI, XSS

Detects directive injection vulnerabilities in template systems. This rule is part of eslint-plugin-secure-coding.

💼 This rule is set to error in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-94 (Code Injection), CWE-96 (SSTI)
SeverityHigh (CVSS 8.8)
Auto-Fix💡 Suggestions available
CategoryInjection Prevention

Vulnerability and Risk

Vulnerability: Directive injection (specifically in frameworks like Angular or Vue) occurs when user-controlled attributes can modify the structure or behavior of the DOM in unexpected ways, potentially leading to Client-Side Template Injection (CSTI) or XSS.

Risk: Attackers can inject malicious directives to execute arbitrary JavaScript code within the victim's session, bypass framework security controls, or manipulate the application's view and logic.

Rule Details

Directive injection occurs when user input is used to inject malicious directives into template systems (Angular, Vue, React, etc.). Attackers can:

  • Execute arbitrary JavaScript code
  • Manipulate the DOM and steal user data
  • Perform cross-site scripting (XSS) attacks
  • Bypass Content Security Policy (CSP)

Why This Matters

IssueImpactSolution
💻 Code ExecutionFull application compromiseUse static directives
🎭 XSSUser session hijackingSanitize template input
🔓 CSP BypassSecurity control evasionValidate directive names

Examples

❌ Incorrect

// Dynamic directive name from user input
const directive = userInput;
<div {...{[directive]: value}} />

// Template injection in Angular
const template = `<div ${userControlledDirective}>Content</div>`;
this.compile(template);

// dangerouslySetInnerHTML with user content
<div dangerouslySetInnerHTML={{__html: userHtml}} />

// Vue v-html with untrusted content
<div v-html="userContent"></div>

✅ Correct

// Use hardcoded directive names
<div onClick={handleClick} />

// Sanitize HTML before rendering
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(userHtml)}} />

// Use trusted templates only
const template = trustedTemplates[templateId];
this.compile(template);

// Validate directive names against whitelist
const allowedDirectives = ['onClick', 'onChange', 'onSubmit'];
if (allowedDirectives.includes(directive)) {
  <div {...{[directive]: value}} />
}

Configuration

{
  rules: {
    'secure-coding/no-directive-injection': ['error', {
      trustedDirectives: ['onClick', 'onChange', 'onSubmit'],
      frameworks: ['react', 'angular', 'vue'],
      allowDynamicInComponents: false
    }]
  }
}

Options

OptionTypeDefaultDescription
trustedDirectivesstring[][]Allowed directive names
userInputVariablesstring[]['req', 'request', 'input']User input variable patterns
frameworksstring[]['react', 'angular', 'vue']Frameworks to check
allowDynamicInComponentsbooleanfalseAllow dynamic directives in safe contexts

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-94 OWASP:A05 CVSS:9.8 | Code Injection detected | CRITICAL [SOC2,PCI-DSS,ISO27001]
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A05_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-94 OWASP:A05 CVSS:9.8
Issue DescriptionSpecific vulnerabilityCode Injection detected
Severity & ComplianceImpact assessmentCRITICAL [SOC2,PCI-DSS,ISO27001]
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Query from Variable

Why: Query strings from variables not traced.

// ❌ NOT DETECTED - Query from variable
const query = `SELECT * FROM users WHERE id = ${userId}`;
db.execute(query);

Mitigation: Always use parameterized queries.

Custom Query Builders

Why: Custom ORM/query builders not recognized.

// ❌ NOT DETECTED - Custom builder
customQuery.where(userInput).execute();

Mitigation: Review all query builder patterns.

Template Engines

Why: Template-based queries not analyzed.

// ❌ NOT DETECTED - Template
executeTemplate('query.sql', { userId });

Mitigation: Validate all template variables.

Further Reading

On this page