flawopen.com/SQL Injection/Stored procedures

Are stored procedures immune to SQL injection?

Reference page — draft, pending review
Short answer

No — a common misconception. A stored procedure protects you only if it uses parameter binding internally. One that builds a query by concatenating its own input parameters into a string and executing it with EXEC or sp_executesql is exactly as vulnerable as application-level string concatenation.

UNSAFE — dynamic SQL built inside it
CREATE PROCEDURE GetUser
  @UserId NVARCHAR(50)
AS
  DECLARE @sql NVARCHAR(MAX)
  SET @sql = 'SELECT * FROM Users WHERE Id = '
    + @UserId
  EXEC(@sql)
SAFE — parameterized inside the procedure
CREATE PROCEDURE GetUser
  @UserId INT
AS
  SELECT * FROM Users
  WHERE Id = @UserId

Why this misconception is common

"Use stored procedures" is often repeated as a blanket SQL-injection fix, and it's true if the procedure itself uses its parameters as bound values in a normal query. The moment a procedure builds a dynamic SQL string internally using EXEC or sp_executesql — often done to allow dynamic table/column names or optional filter clauses — it reintroduces exactly the same risk it was meant to prevent, just one layer removed from the application code.

FAQ

Is sp_executesql ever safe?

Yes, when used with its own parameterization support (sp_executesql @sql, N'@id INT', @id) rather than concatenating the parameter directly into @sql.

References