Communitygithub.com

perl-security

Segurança abrangente para Perl, abrangendo modo taint, validação de entrada, execução segura de processos, consultas parametrizadas DBI, segurança web (XSS/SQLi/CSRF) e políticas de segurança perlcritic. Ative ao revisar manipulação de entrada, execução de processos, consultas DBI ou código voltado para web em Perl.

O que é perl-security?

Este skill fornece um guia completo de segurança para aplicações Perl, cobrindo desde o modo taint (`-T`) até anti-padrões comuns. Ele é especialmente útil para desenvolvedores que trabalham com frameworks web (Mojolicious, Dancer2, Catalyst), manipulam entrada de usuário, realizam operações de arquivo ou banco de dados, e precisam garantir que seu código seja resistente a injeção de comandos, SQLi, XSS e CSRF. O skill apresenta padrões de validação com allowlists, uso seguro de placeholders em DBI, a forma de lista para execução de processos (`system(@cmd)`), prevenção de path traversal e proteção ReDoS, além de incluir configurações prontas para perlcritic. Ele pode ser ativado durante revisões de código, desenvolvimento de novas funcionalidades ou auditorias de segurança, oferecendo exemplos de código em Perl moderno (v5.36) e enfatizando práticas como `sysopen` atômico, escapes de HTML/URL/JSON e uso de tokem CSRF com `urandom`. A abordagem é Defesa em Profundidade, não confiando em apenas uma camada de proteção.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/perl-security

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Padrões de Segurança em Perl

Diretrizes abrangentes de segurança para aplicações Perl, cobrindo validação de entrada, prevenção de injeção e práticas de codificação segura.

Quando Ativar

  • Manipulando entrada de usuário em aplicações Perl
  • Construindo aplicações web em Perl (CGI, Mojolicious, Dancer2, Catalyst)
  • Revisando código Perl em busca de vulnerabilidades de segurança
  • Realizando operações de arquivo com caminhos fornecidos pelo usuário
  • Executando comandos do sistema a partir do Perl
  • Escrevendo consultas de banco de dados DBI

Como Funciona

Comece com limites de entrada cientes de taint, depois vá para fora: valide e descontamine entradas, mantenha o sistema de arquivos e a execução de processos restritos, e use consultas DBI parametrizadas em todos os lugares. Os exemplos abaixo mostram os padrões seguros que este skill espera que você aplique antes de enviar código Perl que toca em entrada do usuário, shell ou rede.

Modo Taint

O modo taint do Perl (-T) rastreia dados de fontes externas e impede que sejam usados em operações inseguras sem validação explícita.

Habilitando o Modo Taint

#!/usr/bin/perl -T
use v5.36;

# Contaminado: qualquer coisa vinda de fora do programa
my $input    = $ARGV[0];        # Contaminado
my $env_path = $ENV{PATH};      # Contaminado
my $form     = <STDIN>;         # Contaminado
my $query    = $ENV{QUERY_STRING}; # Contaminado

# Sanitize PATH no início (obrigatório no modo taint)
$ENV{PATH} = '/usr/local/bin:/usr/bin:/bin';
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};

Padrão de Descontaminação

use v5.36;

# Bom: Valide e descontamine com uma regex específica
sub descontaminar_usuario($input) {
    if ($input =~ /^([a-zA-Z0-9_]{3,30})$/) {
        return $1;  # $1 está descontaminado
    }
    die "Nome de usuário inválido: deve ter 3-30 caracteres alfanuméricos\n";
}

# Bom: Valide e descontamine um caminho de arquivo
sub descontaminar_arquivo($input) {
    if ($input =~ m{^([a-zA-Z0-9._-]+)$}) {
        return $1;
    }
    die "Nome de arquivo inválido: contém caracteres inseguros\n";
}

# Ruim: Descontaminação excessivamente permissiva (anula o propósito)
sub mau_descontaminar($input) {
    $input =~ /^(.*)$/s;
    return $1;  # Aceita QUALQUER COISA — inútil
}

Validação de Entrada

Allowlist em vez de Blocklist

use v5.36;

# Bom: Allowlist — defina exatamente o que é permitido
sub validar_campo_ordenacao($campo) {
    my %permitidos = map { $_ => 1 } qw(name email created_at updated_at);
    die "Campo de ordenação inválido: $campo\n" unless $permitidos{$campo};
    return $campo;
}

# Bom: Valide com padrões específicos
sub validar_email($email) {
    if ($email =~ /^([a-zA-Z0-9._%+-]+\@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/) {
        return $1;
    }
    die "Endereço de email inválido\n";
}

sub validar_inteiro($input) {
    if ($input =~ /^(-?\d{1,10})$/) {
        return $1 + 0;  # Coagir para número
    }
    die "Inteiro inválido\n";
}

# Ruim: Blocklist — sempre incompleta
sub mau_validar($input) {
    die "Inválido" if $input =~ /[<>"';&|]/;  # Perde ataques codificados
    return $input;
}

Restrições de Comprimento

use v5.36;

sub validar_comentario($texto) {
    die "Comentário é obrigatório\n"        unless length($texto) > 0;
    die "Comentário excede 10000 caracteres\n" if length($texto) > 10_000;
    return $texto;
}

Expressões Regulares Seguras

Prevenção de ReDoS

O catastrophic backtracking ocorre com quantificadores aninhados em padrões sobrepostos.

use v5.36;

# Ruim: Vulnerável a ReDoS (backtracking exponencial)
my $regex_ruim = qr/^(a+)+$/;           # Quantificadores aninhados
my $regex_ruim2 = qr/^([a-zA-Z]+)*$/;   # Quantificadores aninhados em classe
my $regex_ruim3 = qr/^(.*?,){10,}$/;    # Combinação repetida greedy/lazy

# Bom: Reescreva sem aninhamento
my $regex_bom = qr/^a+$/;             # Quantificador único
my $regex_bom2 = qr/^[a-zA-Z]+$/;     # Quantificador único em classe

# Bom: Use quantificadores possessivos ou grupos atômicos para evitar backtracking
my $regex_seguro = qr/^[a-zA-Z]++$/;             # Possessivo (5.10+)
my $regex_seguro2 = qr/^(?>a+)$/;                # Grupo atômico

# Bom: Imponha timeout em padrões não confiáveis
use POSIX qw(alarm);
sub correspondencia_segura($string, $pattern, $timeout = 2) {
    my $correspondeu;
    eval {
        local $SIG{ALRM} = sub { die "Tempo limite da regex excedido\n" };
        alarm($timeout);
        $correspondeu = $string =~ $pattern;
        alarm(0);
    };
    alarm(0);
    die $@ if $@;
    return $correspondeu;
}

Operações Seguras com Arquivos

Open com Três Argumentos

use v5.36;

# Bom: Open com três argumentos, filehandle lexical, verifique retorno
sub ler_arquivo($caminho) {
    open my $fh, '<:encoding(UTF-8)', $caminho
        or die "Não foi possível abrir '$caminho': $!\n";
    local $/;
    my $conteudo = <$fh>;
    close $fh;
    return $conteudo;
}

# Ruim: Open com dois argumentos com dados do usuário (injeção de comandos)
sub mau_ler($caminho) {
    open my $fh, $caminho;        # Se $caminho = "|rm -rf /", executa comando!
    open my $fh, "< $caminho";   # Injeção de metacaractere de shell
}

Prevenção de TOCTOU e Path Traversal

use v5.36;
use Fcntl qw(:DEFAULT :flock);
use File::Spec;
use Cwd qw(realpath);

# Criação atômica de arquivo
sub criar_arquivo_seguro($caminho) {
    sysopen(my $fh, $caminho, O_WRONLY | O_CREAT | O_EXCL, 0600)
        or die "Não foi possível criar '$caminho': $!\n";
    return $fh;
}

# Valida que o caminho permanece dentro do diretório permitido
sub caminho_seguro($diretorio_base, $caminho_usuario) {
    my $real = realpath(File::Spec->catfile($diretorio_base, $caminho_usuario))
        // die "O caminho não existe\n";
    my $base_real = realpath($diretorio_base)
        // die "O diretório base não existe\n";
    die "Path traversal bloqueado\n" unless $real =~ /^\Q$base_real\E(?:\/|\z)/;
    return $real;
}

Use File::Temp para arquivos temporários (tempfile(UNLINK => 1)) e flock(LOCK_EX) para evitar condições de corrida.

Execução Segura de Processos

system e exec na Forma de Lista

use v5.36;

# Bom: Forma de lista — sem interpolação de shell
sub executar_comando(@cmd) {
    system(@cmd) == 0
        or die "Comando falhou: @cmd\n";
}

executar_comando('grep', '-r', $padrao_usuario, '/var/log/app/');

# Bom: Capture a saída com segurança usando IPC::Run3
use IPC::Run3;
sub capturar_saida(@cmd) {
    my ($stdout, $stderr);
    run3(\@cmd, \undef, \$stdout, \$stderr);
    if ($?) {
        die "Comando falhou (código $?): $stderr\n";
    }
    return $stdout;
}

# Ruim: Forma de string — injeção de shell!
sub mau_buscar($pattern) {
    system("grep -r '$pattern' /var/log/app/");  # Se $pattern = "'; rm -rf / #"
}

# Ruim: Backticks com interpolação
my $saida = `ls $diretorio_usuario`;   # Risco de injeção de shell

Use também Capture::Tiny para capturar stdout/stderr de comandos externos com segurança.

Prevenção de Injeção SQL

Placeholders DBI

use v5.36;
use DBI;

my $dbh = DBI->connect($dsn, $user, $pass, {
    RaiseError => 1,
    PrintError => 0,
    AutoCommit => 1,
});

# Bom: Consultas parametrizadas — sempre use placeholders
sub encontrar_usuario($dbh, $email) {
    my $sth = $dbh->prepare('SELECT * FROM users WHERE email = ?');
    $sth->execute($email);
    return $sth->fetchrow_hashref;
}

sub buscar_usuarios($dbh, $nome, $status) {
    my $sth = $dbh->prepare(
        'SELECT * FROM users WHERE name LIKE ? AND status = ? ORDER BY name'
    );
    $sth->execute("%$nome%", $status);
    return $sth->fetchall_arrayref({});
}

# Ruim: Interpolação de string no SQL (vulnerabilidade SQLi!)
sub mau_encontrar($dbh, $email) {
    my $sth = $dbh->prepare("SELECT * FROM users WHERE email = '$email'");
    # Se $email = "' OR 1=1 --", retorna todos os usuários
    $sth->execute;
    return $sth->fetchrow_hashref;
}

Allowlists para Colunas Dinâmicas

use v5.36;

# Bom: Valide nomes de colunas contra uma allowlist
sub ordenar_por($dbh, $coluna, $direcao) {
    my %colunas_permitidas = map { $_ => 1 } qw(name email created_at);
    my %direcoes_permitidas = map { $_ => 1 } qw(ASC DESC);

    die "Coluna inválida: $coluna\n"    unless $colunas_permitidas{$coluna};
    die "Direção inválida: $direcao\n" unless $direcoes_permitidas{uc $direcao};

    my $sth = $dbh->prepare("SELECT * FROM users ORDER BY $coluna $direcao");
    $sth->execute;
    return $sth->fetchall_arrayref({});
}

# Ruim: Interpolar coluna escolhida pelo usuário diretamente
sub mau_ordenar($dbh, $coluna) {
    $dbh->prepare("SELECT * FROM users ORDER BY $coluna");  # SQLi!
}

DBIx::Class (Segurança com ORM)

use v5.36;

# DBIx::Class gera consultas parametrizadas seguras
my @usuarios = $schema->resultset('User')->search({
    status => 'active',
    email  => { -like => '%@example.com' },
}, {
    order_by => { -asc => 'name' },
    rows     => 50,
});

Segurança Web

Prevenção de XSS

use v5.36;
use HTML::Entities qw(encode_entities);
use URI::Escape qw(uri_escape_utf8);

# Bom: Codifique a saída para contexto HTML
sub html_seguro($entrada_usuario) {
    return encode_entities($entrada_usuario);
}

# Bom: Codifique para contexto de URL
sub parametro_url_seguro($valor) {
    return uri_escape_utf8($valor);
}

# Bom: Codifique para contexto JSON
use JSON::MaybeXS qw(encode_json);
sub json_seguro($dados) {
    return encode_json($dados);  # Lida com escaping
}

# Escapamento automático em templates (Mojolicious)
# <%= $entrada_usuario %>   — auto-escapado (seguro)
# <%== $html_cru %>          — saída crua (perigoso, use apenas para conteúdo confiável)

# Escapamento automático em templates (Template Toolkit)
# [% entrada_usuario | html %]  — codificação HTML explícita

# Ruim: Saída crua em HTML
sub html_ruim($input) {
    print "<div>$input</div>";  # XSS se $input contiver <script>
}

Proteção CSRF

use v5.36;
use Crypt::URandom qw(urandom);
use MIME::Base64 qw(encode_base64url);

sub gerar_token_csrf() {
    return encode_base64url(urandom(32));
}

Use comparação de tempo constante ao verificar tokens. A maioria dos frameworks web (Mojolicious, Dancer2, Catalyst) fornece proteção CSRF embutida — prefira essas soluções em vez de implementações manuais.

Segurança de Sessão e Cabeçalhos

use v5.36;

# Mojolicious sessão + cabeçalhos
$app->secrets(['segredo-longo-aletatório-rotacionado-regularmente']);
$app->sessions->secure(1);          # Apenas HTTPS
$app->sessions->samesite('Lax');

$app->hook(after_dispatch => sub ($c) {
    $c->res->headers->header('X-Content-Type-Options' => 'nosniff');
    $c->res->headers->header('X-Frame-Options'        => 'DENY');
    $c->res->headers->header('Content-Security-Policy' => "default-src 'self'");
    $c->res->headers->header('Strict-Transport-Security' => 'max-age=31536000; includeSubDomains');
});

Codificação de Saída

Sempre codifique a saída para seu contexto: HTML::Entities::encode_entities() para HTML, URI::Escape::uri_escape_utf8() para URLs, JSON::MaybeXS::encode_json() para JSON.

Segurança de Módulos CPAN

  • Fixar versões no cpanfile: requires 'DBI', '== 1.643';
  • Preferir módulos mantidos: Verifique MetaCPAN por lançamentos recentes
  • Minimizar dependências: Cada dependência é uma superfície de ataque

Ferramentas de Segurança

Políticas de Segurança do perlcritic

# .perlcriticrc — configuração focada em segurança
severity = 3
theme = security + core

# Exigir open com três argumentos
[InputOutput::RequireThreeArgOpen]
severity = 5

# Exigir chamadas de sistema verificadas
[InputOutput::RequireCheckedSyscalls]
functions = :builtins
severity = 4

# Proibir eval com string
[BuiltinFunctions::ProhibitStringyEval]
severity = 5

# Proibir operadores backtick
[InputOutput::ProhibitBacktickOperators]
severity = 4

# Exigir verificação de taint em CGI
[Modules::RequireTaintChecking]
severity = 5

# Proibir open com dois argumentos
[InputOutput::ProhibitTwoArgOpen]
severity = 5

# Proibir filehandles sem palavra
[InputOutput::ProhibitBarewordFileHandles]
severity = 5

Executando perlcritic

# Verificar um arquivo
perlcritic --severity 3 --theme security lib/MyApp/Handler.pm

# Verificar projeto inteiro
perlcritic --severity 3 --theme security lib/

# Integração CI
perlcritic --severity 4 --theme security --quiet lib/ || exit 1

Lista de Verificação Rápida de Segurança

VerificaçãoO que Validar
Modo taintFlag -T em scripts CGI/web
Validação de entradaPadrões allowlist, limites de comprimento
Operações com arquivosOpen com três argumentos, verificação de path traversal
Execução de processosForma de lista do system, sem interpolação de shell
Consultas SQLPlaceholders DBI, nunca interpolar
Saída HTMLencode_entities(), auto-escapamento de template
Tokens CSRFGerados, verificados em requisições que alteram estado
Configuração de sessãoCookies Secure, HttpOnly, SameSite
Cabeçalhos HTTPCSP, X-Frame-Options, HSTS
DependênciasVersões fixadas, módulos auditados
Segurança de regexSem quantificadores aninhados, padrões ancorados
Mensagens de erroNenhum stack trace ou caminho vazado para usuários

Anti-Padrões

# 1. Open com dois argumentos com dados do usuário (injeção de comandos)
open my $fh, $entrada_usuario;               # Vulnerabilidade CRÍTICA

# 2. system na forma de string (injeção de shell)
system("convert $arquivo_usuario output.png"); # Vulnerabilidade CRÍTICA

# 3. Interpolação de string SQL
$dbh->do("DELETE FROM users WHERE id = $id");  # SQLi

# 4. eval com entrada do usuário (injeção de código)
eval $codigo_usuario;                         # Execução remota de código

# 5. Confiar em $ENV sem sanitizar
my $caminho = $ENV{UPLOAD_DIR};             # Pode ser manipulado
system("ls $caminho");                      # Dupla vulnerabilidade

# 6. Desativar taint sem validação
($input) = $input =~ /(.*)/s;           # Descontaminação preguiçosa — anula propósito

# 7. Dados crus do usuário em HTML
print "<div>Bem-vindo, $username!</div>";  # XSS

# 8. Redirecionamentos não validados
print $cgi->redirect($url_usuario);         # Redirecionamento aberto

Lembre-se: A flexibilidade do Perl é poderosa, mas requer disciplina. Use o modo taint para código voltado para web, valide todas as entradas com allowlists, use placeholders DBI para todas as consultas e codifique toda a saída para seu contexto. Defesa em profundidade — nunca confie em uma única camada.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Habilidades Relacionadas