T09 · Insecure Skill Coding Practices
Error
- Location
- emitir_nfse.py:285
- Finding
- Unsigned user input is interpolated into XML before privileged signing and transmission<![CDATA[ ## Vulnerability Details **File Location**: `emitir_nfse.py:285-342`; related patterns also occur in `cancelar_nfse.py:47-62` and `baixar_notas.py:58-73` **Vulnerability Type**: XML injection through string interpolation **Risk Level**: High ### Vulnerable Code ```python xml_template = f"""<PedidoEnvioLoteRPS xmlns="http://www.prefeitura.sp.gov.br/nfe" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Cabecalho xmlns="" Versao="1"> <CPFCNPJRemetente> <CNPJ>{config['cnpj_prestador']}</CNPJ> </CPFCNPJRemetente> <transacao>false</transacao> <dtInicio>{nota['data_emissao']}</dtInicio> <dtFim>{nota['data_emissao']}</dtFim> <QtdRPS>1</QtdRPS> <ValorTotalServicos>{formata_valor(nota['valor_servicos'])}</ValorTotalServicos> <ValorTotalDeducoes>{formata_valor(nota.get('valor_deducoes', 0))}</ValorTotalDeducoes> </Cabecalho> <RPS xmlns=""> <Assinatura>{assinatura_rps}</Assinatura> <ChaveRPS> <InscricaoPrestador>{config['inscricao_municipal']}</InscricaoPrestador> <SerieRPS>{config['serie_rps']}</SerieRPS> <NumeroRPS>{nota['numero_rps']}</NumeroRPS> </ChaveRPS> <TipoRPS>RPS</TipoRPS> <DataEmissao>{nota['data_emissao']}</DataEmissao> <StatusRPS>{nota['status_rps']}</StatusRPS> <TributacaoRPS>{config['tributacao_rps']}</TributacaoRPS> <ValorServicos>{formata_valor(nota['valor_servicos'])}</ValorServicos> <ValorDeducoes>{formata_valor(nota.get('valor_deducoes', 0))}</ValorDeducoes> {f"<ValorPIS>{formata_valor(v_pis)}</ValorPIS>" if v_pis > 0 else ""} {f"<ValorCOFINS>{formata_valor(v_cofins)}</ValorCOFINS>" if v_cofins > 0 else ""} {f"<ValorINSS>{formata_valor(v_inss)}</ValorINSS>" if v_inss > ...[truncated 4112 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Replace string-built XML with `lxml.etree.Element` and `lxml.etree.SubElement`. - Assign untrusted values only through each element's `.text` property so the XML library performs escaping. - Apply strict allow-list validation before signing: - Invoice and RPS numbers: digits only with documented length limits. - Dates: valid ISO dates within an authorized range. - Status and retention indicators: fixed enumerations. - CNPJ and CPF fields: digits only with expected lengths and checksum validation. - State: two uppercase letters from the supported set. - Municipality and service codes: digits only with fixed limits. - Email: validated address format without control characters. - Monetary values: bounded, non-negative decimal values. - Validate the completed XML against the official municipal XSD before signing. - Present a canonical summary of security-sensitive fields to the user immediately before a production signature is created. - Apply the same element-builder and validation approach to issuance, cancellation, consultation, and reporting scripts. ]]>
