I think I've seen this question elsewhere, and I probably asked for more info. And I'm doing it again. What is your purpose with this? Why are you using dynamic SQL? What part of your SQL is dynamic, and what part of the input can be modified by the evil criminal?
Without such details, all we can do is propose something, and then somebody else can counter that proposal by injecting something, just like I'll do below with Dominique's example (with no critique intended, again difficult to be precise with so little info.
So please explain why use dynamic SQL and why not just have two parameters to the stored procedure (one for each value to be used in the VALUES clause for the INSERT statement).
Anyhow, here is the proposed answer modified with an injected TRUNCATE TABLE:
DROP TABLE IF EXISTS SomeVeryImportantData
DROP TABLE IF EXISTS #ThisIsATable
CREATE TABLE SomeVeryImportantData (id int, txt varchar(30));
INSERT INTO SomeVeryImportantData VALUES (1,'some important txt');
DECLARE @param1 int;
DECLARE @param2 varchar(30);
DECLARE @TSQL nvarchar(MAX) = N'SELECT @param1, @param2 truncate table SomeVeryImportantData';
CREATE TABLE #ThisIsATable (Id INT, VAL NVARCHAR(10));
INSERT INTO #ThisIsATable
EXEC [dbo].[sp_executesql] @TSQL, N'@param1 int, @param2 varchar(30)', @param1=@param1, @param2=@param2
SELECT * FROM SomeVeryImportantData;
SELECT * FROM #ThisIsATable;