garrytan/gstack · warning · Error

Invalid CSS property name: ${property}. Only letters and hyp

Error message

Invalid CSS property name: ${property}. Only letters and hyphens allowed.

What it means

Thrown by `browse style` when the property name fails the regex `/^[a-zA-Z-]+$/`. The command only accepts standard CSS property names composed of ASCII letters and hyphens (e.g. `color`, `background-color`, `font-size`). This guards the subsequent `modifyStyle` call which interpolates the property into a CSS rule string, preventing injection of arbitrary CSS or JS-triggers via the property slot. Note CSS custom properties (`--my-var`) are NOT accepted because the regex requires at least one letter and allows hyphens but the leading `--` form has no letter before the first hyphen segment — actually `--my-var` contains letters so it PASSES; the real rejection targets underscores, digits-leading tokens, and non-ASCII.

Source

Thrown at browse/src/write-commands.ts:780

    case 'style': {
      // style --undo [N] → revert modification
      if (args[0] === '--undo') {
        const idx = args[1] ? parseInt(args[1], 10) : undefined;
        await undoModification(page, idx);
        return idx !== undefined ? `Reverted modification #${idx}` : 'Reverted last modification';
      }

      // style <selector> <property> <value>
      const [selector, property, ...valueParts] = args;
      const value = valueParts.join(' ');
      if (!selector || !property || !value) {
        throw new Error('Usage: browse style <sel> <prop> <value> | style --undo [N]');
      }

      // Validate CSS property name
      if (!/^[a-zA-Z-]+$/.test(property)) {
        throw new Error(`Invalid CSS property name: ${property}. Only letters and hyphens allowed.`);
      }

      // Validate CSS value — block data exfiltration patterns
      const DANGEROUS_CSS = /url\s*\(|expression\s*\(|@import|javascript:|data:/i;
      if (DANGEROUS_CSS.test(value)) {
        throw new Error('CSS value rejected: contains potentially dangerous pattern.');
      }

      const mod = await modifyStyle(page, selector, property, value);
      return `Style modified: ${selector} { ${property}: ${mod.oldValue || '(none)'} → ${value} } (${mod.method})`;
    }

    case 'cleanup': {
      // Parse flags
      let doAds = false, doCookies = false, doSticky = false, doSocial = false;
      let doOverlays = false, doClutter = false;
      let doAll = false;

View on GitHub (pinned to 94993f7401)

Solutions

  1. Use the CSS kebab-case property name: `background-color`, not `backgroundColor` or `background_color`.
  2. Ensure the property contains only ASCII letters and hyphens — no underscores, digits at the start, or punctuation.
  3. Custom properties (`--my-var`) are accepted as they contain letters and hyphens.
  4. If you need to set a property the regex rejects, verify it is a real CSS property; non-standard or invented names are intentionally blocked.

Example fix

// before
await runBrowseCommand(['style', 'body', 'background_color', 'red']);

// after
await runBrowseCommand(['style', 'body', 'background-color', 'red']);
Defensive patterns

Strategy: validation

Validate before calling

function validateCssProperty(property: string): void {
  if (!/^[a-zA-Z-]+$/.test(property)) {
    throw new Error(`Invalid CSS property name: ${property}. Only ASCII letters and hyphens allowed.`);
  }
}

Type guard

function isCssPropertyName(s: string): boolean {
  return /^[a-zA-Z-]+$/.test(s);
}

Prevention

When it happens

Trigger: Passing `background_color` (underscore not allowed), `backgroundColor` (camelCase — no hyphen, but the letters pass... actually camelCase like `backgroundColor` matches `[a-zA-Z-]+` since it is all letters with no hyphen, so it PASSES the regex but may not be a valid CSS property in that form); `1color` (leading digit rejected); `color!` (punctuation rejected); a property name with a trailing space that survived trim.

Common situations: User passes a JavaScript CSSOM camelCase name (`backgroundColor`) instead of the CSS kebab-case (`background-color`) — note this passes the regex but `modifyStyle` may still mis-handle it; user passes a vendor-prefixed property with an underscore typo; an LLM emits `--custom` with a leading space; a property name copied from a minified CSS source contained an escape character.

Related errors


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/ad9d8ef7511b82ff. Report an issue: GitHub.