Tencent/WeKnora · error

access to '%s' is not allowed

Error message

access to '%s' is not allowed

What it means

The identifier validator rejected a column whose lowercased name starts with pg_, reserving PostgreSQL's pg_* namespace (system catalogs like pg_catalog, pg_class, pg_attribute). Blocking this prefix prevents injected expressions from referencing catalog tables or shadowing catalog functions for information disclosure. It follows the exact-match system column check in the same function.

Source

Thrown at internal/utils/inject.go:2351

func (v *sqlValidator) validateColumnRef(cr *pg_query.ColumnRef) error {
	if !v.checkSystemColumns {
		return nil
	}

	// Check for system column access
	for _, field := range cr.Fields {
		if s := field.GetString_(); s != nil {
			colName := strings.ToLower(s.Sval)
			// Block access to system columns
			systemColumns := []string{"xmin", "xmax", "cmin", "cmax", "ctid", "tableoid"}
			for _, sysCol := range systemColumns {
				if colName == sysCol {
					return fmt.Errorf("access to system column '%s' is not allowed", colName)
				}
			}
			// Block pg_ prefixed identifiers
			if strings.HasPrefix(colName, "pg_") {
				return fmt.Errorf("access to '%s' is not allowed", colName)
			}
		}
	}
	return nil
}

// getTypeName extracts the type name from a TypeName node
func (v *sqlValidator) getTypeName(tn *pg_query.TypeName) string {
	var parts []string
	for _, name := range tn.Names {
		if s := name.GetString_(); s != nil {
			parts = append(parts, s.Sval)
		}
	}
	return strings.Join(parts, ".")
}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Rename any application column that starts with pg_ to a non-reserved name
  2. Remove pg_* function/table references from the expression; use allowlisted equivalents
  3. For catalog inspection, connect directly with a DBA tool instead of validated expressions
  4. Audit generated SQL from ORMs/LLMs for pg_-prefixed helpers before submitting

Example fix

// before
filter := "pg_sleep(5) IS NULL"
// after
// remove the call entirely; delay tactics have no valid use in filters
filter := "status = 'active'"
Defensive patterns

Strategy: validation

Validate before calling

func usesPgReservedPrefix(ident string) bool {
    return strings.HasPrefix(strings.ToLower(ident), "pg_")
}
// reject before submission
if usesPgReservedPrefix(columnName) { return errors.New("identifiers must not start with pg_") }

Type guard

func isSafeIdentifier(name string) bool {
    if name == "" { return false }
    n := strings.ToLower(name)
    if strings.HasPrefix(n, "pg_") { return false }
    for _, c := range n {
        if !(c == '_' || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { return false }
    }
    return true
}

Try / catch

if err := injector.Validate(expr); err != nil {
    if strings.Contains(err.Error(), "is not allowed") && strings.Contains(strings.ToLower(err.Error()), "pg_") {
        return fmt.Errorf("identifier uses the reserved pg_ prefix: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: An expression or filter containing an identifier like pg_sleep, pg_read_file, pg_catalog.pg_class, or a user column accidentally named pg_owner passed through the identifier validation path (field.GetString_() branch).

Common situations: Time-based injection attempts using pg_sleep; catalog-enumeration queries (pg_tables, pg_user) pasted into filters; legitimate columns whose names collide with the pg_ prefix after a schema rename.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/9c47bf5523993c12. Report an issue: GitHub.