rule-based deletions from string list

You would need something like DeleteSubsequenceCases, but it doesn't exist. I would recommend this instead:

SequenceReplace[lis, {d_?(StringMatchQ[NumberString]), ___, "X"} :> d]

If X only appears once, you could also use this:

First@SequenceCases[lis, {a___, d_?(StringMatchQ[NumberString]), ___, "X", b___} :> {a, "12", b}]

Replace[lis, {a___, b_String?(StringMatchQ[NumberString]), Shortest[c___], "X", d___} :> 
  {a, b, d}]

{"a", "b", "c", "12", "s"}


rlis = Reverse[lis];
xpos = First[Flatten[Position[StringMatchQ[rlis, "X"], True]]];
Reverse[Drop[rlis, {xpos, xpos + LengthWhile[rlis[[xpos + 1 ;;]], 
     StringMatchQ[#, NumberString] == False &]}]]

{"a", "b", "c", "12", "s"}