# Twig Audit

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-trebormc-drupal-ai-agents-twig-audit`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [trebormc](https://agentstack.voostack.com/s/trebormc)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [trebormc](https://github.com/trebormc)
- **Source:** https://github.com/trebormc/drupal-ai-agents/tree/main/.claude/skills/twig-audit

## Install

```sh
agentstack add skill-trebormc-drupal-ai-agents-twig-audit
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Twig Audit

**Principle: Twig is for presentation ONLY. Preprocess handles logic.**

## Audit Workflow

1. Run the detection greps below on the theme/module templates.
2. Read EVERY flagged template in full (grep hits need context to confirm).
3. Classify each confirmed hit against the anti-pattern list (severity: drilling/raw = CRITICAL, logic/isolation = HIGH, attributes = MEDIUM).
4. Produce the report using the Audit Report Format at the end.

## Detection Commands

Replace `TPL` with the templates directory, e.g. `$DDEV_DOCROOT/themes/custom/*/templates/`:

```bash
# Anti-pattern 1: render array drilling — matches content.field_x[0]['#markup'] and ['#items']
grep -rn "\[.['\"]#" TPL ; grep -rn "\['#" TPL

# Anti-pattern 2: business logic — comparisons/calculations on .value inside if/set
grep -rnE "\{% *(if|set) .*\.value" TPL

# Anti-pattern 3: raw filter usage — every hit must be justified
grep -rn "|raw" TPL

# Anti-pattern 4: non-isolated includes — check each hit for "with_context = false" or "only"
grep -rn "include(" TPL ; grep -rn "{% embed" TPL

# Anti-pattern 6: direct entity access bypassing the render system
grep -rn "\.entity\." TPL

# Anti-pattern 7: attributes built as strings
grep -rnE "class=\"[^\"]*\{\{" TPL
```

A grep hit is a CANDIDATE, not a confirmed issue — always read the template before reporting.

## Anti-Patterns to Detect

### 1. Render Array Drilling (CRITICAL — Breaks Cache)
```twig
{# BAD — loses cache metadata, security risk #}
{{ content.field_image[0]['#markup'] }}
{{ content.field_body['#items'][0]['value'] }}

{# GOOD #}
{{ content.field_image }}
{{ content.body }}
```

### 2. Business Logic in Templates
```twig
{# BAD #}
{% if user.field_role.value == 'premium' and user.field_expiration.value|date('U') > 'now'|date('U') %}
  {% set discount = product.price.value * 0.2 %}

{# GOOD — variable from preprocess #}
{% if has_premium_discount %}
  {{ formatted_discounted_price }}
```

### 3. Unsafe |raw Usage
```twig
{# BAD — XSS vulnerability #}
{{ node.field_user_content.value|raw }}

{# GOOD — use processed field #}
{{ content.field_user_content }}
```

### 4. Missing Component Isolation
```twig
{# BAD — variable contamination #}
{{ include('mytheme:card', {heading: title}) }}

{# GOOD #}
{{ include('mytheme:card', {heading: title}, with_context = false) }}
{% embed 'mytheme:card' with {heading: title} only %}
```

Use `include` (+ `with_context = false`) when only passing simple values; use `embed` (+ `only`) when the component has blocks/slots to fill. Both isolate the component from the parent template's variables.

### 5. Content Not Rendered (Loses Cache Metadata)
```twig
{# BAD — cache metadata lost #}
{{ label }}
{{ content.body }}

{# GOOD — render remaining with without #}
{{ label }}
{{ content.body }}
{{ content|without('body') }}
```

### 6. Direct Entity Access (Bypasses Render System)
```twig
{# BAD — bypasses formatters and cache #}
{{ file_url(node.field_image.entity.uri.value) }}

{# GOOD — render the field properly #}
{{ content.field_image }}

{# Or if you need just the URL, use preprocess #}
{{ image_url }}
```

### 7. Attributes as Strings
```twig
{# BAD #}

{# GOOD #}
{% set classes = ['node', 'node--' ~ node.bundle|clean_class] %}

```

## Component Props vs Slots

| Props (simple values) | Slots (complex content) |
|----------------------|------------------------|
| Titles, labels | Formatted text fields |
| Numbers, booleans | Images, media |
| URLs | Entity references |
| CSS variants | Nested components |

## Correct Adapter Pattern
```twig
{# node--article--teaser.html.twig #}
{% embed 'mytheme:card' with {
  heading: label,
  url: url,
  variant: node.isPromoted ? 'featured' : 'default',
} only %}
  {% block media %}{{ content.field_image }}{% endblock %}
  {% block body %}{{ content.body }}{% endblock %}
{% endembed %}

{# CRITICAL: Render remaining for cache bubbling #}
{{ content|without('field_image', 'body') }}
```

## Move to Preprocess

Flag these as preprocess candidates:
- Entity queries
- Service calls
- Complex calculations
- Permission checks
- Date formatting beyond simple `|date`

## Audit Report Format

### Issues Detected
| Severity | Line | Issue | Risk |
|----------|------|-------|------|
| CRITICAL | 12 | Render array drilling | Broken cache |

### Refactored Code
Complete template with fixes and comments.

### Preprocess Changes
```php
function mytheme_preprocess_node(&$variables) {
  // Required PHP code for logic moved from template
}
```

### Final Checklist
- [ ] No render array drilling
- [ ] content rendered or `|without` used
- [ ] No business logic
- [ ] `|raw` only with trusted data
- [ ] Components isolated
- [ ] Attributes via object

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [trebormc](https://github.com/trebormc)
- **Source:** [trebormc/drupal-ai-agents](https://github.com/trebormc/drupal-ai-agents)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-trebormc-drupal-ai-agents-twig-audit
- Seller: https://agentstack.voostack.com/s/trebormc
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
